package server;

import java.io.PrintWriter;
import java.util.ArrayList;

import artifacts.*;
import test.Main;
import maze.*;

/**
 * @author Denis Toikka
 * Game process.
 *
 */
public class Game {
	
	/**
	 * Game maze.
	 */
	public Maze maze = null;
	/**
	 * Check if need to stop server.
	 */
	boolean stopProgram = false;
	/**
	 * All players for this session.
	 */
	ArrayList<Player> players = new ArrayList<Player>();
	
	/**
	 * Constructor.
	 */
	public Game() {
		this.maze = createMaze();
		Main.log.print("Server started.");
	}
	
	/**
	 * @return
	 * Adding new player to the game.
	 */
	public Player createNewPlayer() {
		Player player = new Player();
		player.Enter(this.maze);
		this.players.add(player);
		Artifact.addArtsToMaze(this.maze);
		return player;
	}
	
	/**
	 * Client has left server, check if need to stop process.
	 */
	public void endThisPart() {
		if(!this.stopProgram) startNewPart();
	}
	
	/**
	 * New client entered to server.
	 */
	public void startNewPart() {
		try {
			Main.server = new Communications();
			Main.server.setConnection(this);
		} catch (Exception e) {
			Main.log.print(e);
		}
	}
	
	/**
	 * @param fromClient
	 * @param pl
	 * @param netOut
	 * @return
	 * Process main commands.
	 */
	String processCommand(String fromClient, Player pl, PrintWriter netOut) {
		String response = "";
		String[] command = fromClient.split(" ");
		if("LOOK".equalsIgnoreCase(fromClient)) {
			response = look(pl);
		}
		else if("NORTH".equalsIgnoreCase(fromClient) ||
				"SOUTH".equalsIgnoreCase(fromClient) ||
				"EAST".equalsIgnoreCase(fromClient)  ||
				"WEST".equalsIgnoreCase(fromClient)) {
			String direction = Character.toString(fromClient.charAt(0));
			response = move(pl, direction, fromClient, netOut);
		}
		else if("HOME".equalsIgnoreCase(fromClient)) {
			pl.currentRoom = this.maze.entry;
			response = "You are magically transported to the entry of the " + this.maze.name;
		}
		else if("TAKE".equalsIgnoreCase(command[0])) {
			String item = "";
			for(int j = 1; j < command.length; j++) {
				if(item == "") item += command[j];
				else item = item + " " + command[j];
			}
			if("ALL".equalsIgnoreCase(item)) response = takeAllItems(pl);
			else response = takeItem(item, pl);
		}
		else if("STATUS".equalsIgnoreCase(fromClient)) {
			printStatus(pl, netOut);
		}
		else response = "Unknown command";
		return response;
	}
	
	/**
	 * @return
	 * Create maze.
	 */
	private Maze createMaze() {
		Maze newMaze = new Maze();
		newMaze.createMaze();
		return newMaze;
	}
	
	/**
	 * @param pl
	 * @return
	 * LOOK command.
	 */
	String look(Player pl) {
		String response = "";
		response = "You find yourself in room " + pl.getRoom().getName() +
		". Exists: " + pl.currentRoom.existDoor();
		if(!pl.currentRoom.items.isEmpty()) {
			String items = items(pl.currentRoom.items);
			response = response + " " + items + " lie on the floor.";
		}
		String zombie = "";
		for(Player player : this.players) {
			if(player != pl && player.currentRoom == pl.currentRoom && 
					player.getName() != "") {
				if(zombie != "") zombie += ", " + player.getName();
				else zombie += player.getName();
			}
		}
		if(zombie != "") response += " Here rest " + zombie + ".";
		return response;
	}
	
	/**
	 * @param pl
	 * @param direction
	 * @param fromClient
	 * @param netOut
	 * @return
	 * NORTH, SOUTH, EAST, WEST commands.
	 */
	String move(Player pl, String direction, String fromClient, PrintWriter netOut) {
		String response = "";
		String[] pathList = {direction};
		if(pl.currentRoom.validatePath(pathList)) {
			Room oldRoom = pl.currentRoom;
			pl.Move(direction);
			response = "Leaving through " + fromClient.toLowerCase() + "ern door.";
			if(pl.currentRoom == Maze.out) {
				int points = 0;
				for(Artifact art : pl.inventory) {
					points += art.getCost();
				}
				pl.reiting = points;
				response += " You have reached the exit of the " + this.maze.name +
				" and collected " + Integer.toString(points) + " points. ";
				Player plM = pl;
				for(Player player : this.players) {
					if(plM.reiting < player.reiting && player.foundAnExit) plM = player;
				}
				if(plM != pl) response += plM.getName() + " was better than you with "
					+ Integer.toString(plM.reiting) + " points. Beat that!";
				else response += "Congratulations, you are a winner!";
				pl.foundAnExit = true;
				netOut.println(response);
				response = "break";
			}
			else if(pl.health <= 0) {
				netOut.println("You died in room " + pl.currentRoom.getName() + ".");
				response = "break";
			}
			else if(pl.currentRoom != oldRoom.getDirection(direction))
				response += " You are teleported into room "	
					+ pl.currentRoom.getName() + ".";
			else 
				response += " You are now in room " 
				+ pl.currentRoom.getName() + ".";
		}
		else response = "You cannot go that way!";
		return response;
	}
	
	/**
	 * @param list
	 * @return
	 * Returns all items in list.
	 */
	String items(ArrayList<Artifact> list) {
		String items = "";
		items = findItemsAmount(Coin.class, list);
		if(items != "") {
			if(findItemsAmount(Goblet.class, list) != "") 
				items = items + ", " + findItemsAmount(Goblet.class, list);
		}
		else items = findItemsAmount(Goblet.class, list);
		if(items != "") {
			if(findItemsAmount(Potion.class, list) != "") 
				items = items + ", " + findItemsAmount(Potion.class, list);
		}
		else items = findItemsAmount(Potion.class, list);
		return items;
	}
	
	/**
	 * @param itemClass
	 * @param list
	 * @return
	 * Returns amount of items.
	 */
	@SuppressWarnings("unchecked")
	String findItemsAmount(Class itemClass, ArrayList<Artifact> list) {
		int count = 0;
		for(Artifact art : list) {
			if(art.getClass() == itemClass) count++;
		}
		if(count > 1) return Integer.toString(count) + " " 
			+ itemClass.getSimpleName().toLowerCase() + "s";
		else if(count == 1) return "1 " + itemClass.getSimpleName().toLowerCase();
		else return "";
	}
	
	/**
	 * @param item
	 * @param pl
	 * @return
	 * TAKE command
	 */
	String takeItem(String item, Player pl) {
		String response = "";
		for(Artifact art : pl.currentRoom.items) {
			if(item.equalsIgnoreCase(art.getClass().getSimpleName())) {
				response = "You grab a " +
					art.getClass().getSimpleName().toLowerCase() +
					" and put it in your inventory.";
				response += art.gateArt(pl);
				pl.currentRoom.items.remove(art);
				break;
			}
		}
		if(response == "") response = "Cannot find any " + 
			item + "s in this room.";
		return response;
	}
	
	/**
	 * @param pl
	 * @return
	 * TAKE ALL command.
	 */
	String takeAllItems(Player pl) {
		String response = "";
		if(pl.currentRoom.items.size() > 0) {
			response = "You grab " + items(pl.currentRoom.items) + " and put it in your inventory.";
			for(Artifact art : pl.currentRoom.items) {
				response += art.gateArt(pl);
			}
			pl.currentRoom.items.clear();
		}
		else response = "Nothing to take.";
		return response;
	}
	
	/**
	 * @param pl
	 * @param netOut
	 * STATUS command.
	 */
	void printStatus(Player pl, PrintWriter netOut) {
		netOut.println("Player:         " + pl.getName());
		netOut.println("Current room:   " + pl.currentRoom.getName());
		netOut.println("Health:         " + pl.health);
		netOut.println("In inventory:   " + items(pl.inventory));
	}
}
